home *** CD-ROM | disk | FTP | other *** search
/ APDL Eductation Resources / APDL Eductation Resources.iso / programs / graphics / gif2rpc / source / 8bpp / c / dither2x2 < prev    next >
Encoding:
Text File  |  1995-10-16  |  5.1 KB  |  156 lines

  1. /* dither2x2.c
  2.  * AUTHOR:      Cy Booker, cy@cheepnis.demon.co.uk
  3.  * LICENSE:     FreeWare, Copyright (c) 1995 Cy Booker
  4.  */
  5.  
  6. #include "internal.h"
  7.  
  8. #include <assert.h>
  9. #include <string.h>             /* memset() */
  10.  
  11. #include "OS:macros.h"
  12. #include "OS:hourglass.h"
  13.  
  14.  
  15. #include <stdio.h>
  16.  
  17. /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  18.  */
  19.  
  20. static void calculate_dither2x2(
  21.                 const process_gif       *p,
  22.                 byte                    dither[2][2],
  23.                 os_colour               colour);
  24.                 
  25.  
  26.  
  27. /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  28.  */
  29.  
  30. extern bool process_gif_8bpp_dither2x2(
  31.                 const process_gif       *p) {
  32.   bits                  *rove;
  33.   bits                  dest;
  34.   int                   width, height;
  35.   int                   x, y;
  36.   const os_colour       *palette;
  37.   int                   line_length;
  38.   bits                  t;
  39.   int                   index;
  40.   byte                  dither[256][2][2];
  41.  
  42.   assert(p);
  43.   assert(p->pixel_width > 0);
  44.   assert(p->pixel_height > 0);
  45.   assert(p->in_palette.colours);
  46.   assert(p->out_palette.colours);
  47.   assert((p->line_length & 3) == 0);
  48.   assert(p->fn);
  49.  
  50.   /*
  51.    * pre-calculate dither table
  52.    * to save a function call in middle loop
  53.    * thus the compiler has more registers to play with
  54.    */
  55.   palette = p->in_palette.colours;
  56.   for (index= p->in_palette.ncolours; (index > 0);) {
  57.     index--;
  58.     calculate_dither2x2(p, dither[index], palette[index]);
  59.   }
  60.  
  61.   /*
  62.    * note we pre-load values from the process_gif structure
  63.    * because it considerably helps the compiler produce better code
  64.    */
  65.   rove = (bits *)p->buffer;
  66.   height = p->pixel_height;
  67.   width = ((p->pixel_width + 3) & ~3) >> 2;
  68.   line_length = p->line_length >> 2;
  69.  
  70.   for (y= height; (y > 0); y--) {
  71.     if ((y & 7) == 0) {
  72.       xhourglass_percentage((y * 100) / height);
  73.     }
  74.     for (x= width - 1; (x >= 0); x--) {
  75.       /*
  76.        * reading/writing one 32-bit word is much faster than four bytes
  77.        */
  78.       t = rove[x];
  79.       dest  = dither[(t << (3*8)) >> 24][y & 1][0] << (0*8);
  80.       dest |= dither[(t << (1*8)) >> 24][y & 1][0] << (2*8);
  81.       dest |= dither[(t << (2*8)) >> 24][y & 1][1] << (1*8);
  82.       dest |= dither[(t << (0*8)) >> 24][y & 1][1] << (3*8);
  83.       rove[x] = dest;
  84.     }
  85.     rove += line_length;
  86.   }
  87.   return FALSE;
  88. }
  89.  
  90.  
  91.  
  92. /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  93.  */
  94.  
  95. static void calculate_dither2x2(
  96.                 const process_gif       *p,
  97.                 byte                    dither[2][2],
  98.                 os_colour               colour) {
  99.   int                   target_red, target_grn, target_blu;
  100.   int                   red, grn, blu;
  101.   rgbtupleout           err;
  102.   register int          err_red, err_grn, err_blu;
  103.   int                   t;
  104.  
  105.  
  106.   err.palette = p->out_palette;                 /* structure copy */
  107.   /*
  108.    * we now use ``colourtrns'' dithering algorithm, where X is the
  109.    * destination colour, and all values are (r, g, b) tuples
  110.    * topleft <-- X
  111.    * bottomright <-- X - (topleft - X)
  112.    * topright <-- X - (((topleft - X) + (bottomright - X)) / 2)
  113.    * bottomleft <-- X - (((topleft - X) + (bottomright - X) + (topright - X)) / 3)
  114.    *
  115.    * personally, I don't see why the need for divisions, as surely we are using:
  116.    *    "OK we missed X by N, therefore compensate by choosing X - N"
  117.    *
  118.    * humph, it works, anyway
  119.    */
  120.  
  121.   target_red = (colour >> (1 * 8)) & 0xff; target_red |= target_red << 8;
  122.   target_grn = (colour >> (2 * 8)) & 0xff; target_grn |= target_grn << 8;
  123.   target_blu = (colour >> (3 * 8)) & 0xff; target_blu |= target_blu << 8;
  124.   dither[0][0] = (*p->fn)(&err, target_red, target_grn, target_blu);
  125.   err_red = err.colour.red; err_grn = err.colour.grn; err_blu = err.colour.blu;
  126.   /*
  127.    * the err.colour is the error in representing the input red, grn, blu
  128.    * on later iterations we need to add in the error of the output colour from the target colour
  129.    */
  130.  
  131.   red = target_red + err_red;
  132.   grn = target_grn + err_grn;
  133.   blu = target_blu + err_blu;
  134.   dither[1][1] = t = (*p->fn)(&err, red, grn, blu);
  135.   red = err.colour.red; grn = err.colour.grn; blu = err.colour.blu;
  136.   err_red += red; err_grn += grn; err_blu += blu;               /* local error */
  137.   red = p->out_palette.colours[t].red; grn = p->out_palette.colours[t].grn; blu = p->out_palette.colours[t].blu;
  138.   err_red += target_red - red; err_grn += target_grn - grn; err_blu += target_blu - blu;
  139.  
  140.   red = target_red + (err_red / 2);
  141.   grn = target_grn + (err_grn / 2);
  142.   blu = target_blu + (err_blu / 2);
  143.   dither[0][1] = t = (*p->fn)(&err, red, grn, blu);
  144.   red = err.colour.red; grn = err.colour.grn; blu = err.colour.blu;
  145.   err_red += red; err_grn += grn; err_blu += blu;               /* local error */
  146.   red = p->out_palette.colours[t].red; grn = p->out_palette.colours[t].grn; blu = p->out_palette.colours[t].blu;
  147.   err_red += target_red - red; err_grn += target_grn - grn; err_blu += target_blu - blu;
  148.  
  149.   red = target_red + (err_red / 3);
  150.   grn = target_grn + (err_grn / 3);
  151.   blu = target_blu + (err_blu / 3);
  152.   dither[1][0] = (*p->fn)(&err, red, grn, blu);
  153. }
  154.  
  155.  
  156.